﻿using KeepAccounts.Services.BaseServices;
using System;
using System.Collections.Generic;
using System.Text;
using KeepAccounts.Models.Models.UserInfo;
using KeepAccounts.Repository;
using System.Threading.Tasks;
using KeepAccounts.Models.ViewModels.UserInfo;
using KeepAccounts.Models.Enums.UserInfo;
using KeepAccounts.Models;
using KeepAccounts.Common.Utilities;
using System.Linq;
using KeepAccounts.Repository.Sms;
using KeepAccounts.Models.Enums.Sms;
using KeepAccounts.Models.Models.Sms;
using Newtonsoft.Json;
using KeepAccounts.Common.HttpContextUser;
using KeepAccounts.Common.Mappers;
using KeepAccounts.Common.Jwt;
using KeepAccounts.Models.PageModel;
using SqlSugar;
using KeepAccounts.Common.Config;
using AutoMapper;
using Senparc.Weixin;
using Senparc.Weixin.WxOpen.Containers;

namespace KeepAccounts.Services.Domain
{
    public class UserInfoServices : BaseServices<UserInfoEntity>, IUserInfoServices
    {
        private readonly IUserInfoRepository _userInfoRepository;
        private readonly ISmsRepository _smsRepository;
        private readonly IAspNetUser _aspNetUser;




        object obj = new object { };
        public UserInfoServices(IUserInfoRepository dal, ISmsRepository smsRepository, IAspNetUser aspNetUser)
        {
            base.BaseDal = dal;
            _userInfoRepository = dal;
            _smsRepository = smsRepository;
            _aspNetUser = aspNetUser;

        }

        public async Task<LoginResultViewModel> Login(LoginQueryModel model)
        {
            CheckLoginModel(model);

            UserInfoEntity userInfoEntity = null;
            if (model.LoginType == LoginTypeEnum.密码登录)
            {
                userInfoEntity = await CheckPassword(model);
            }
            else if (model.LoginType == LoginTypeEnum.验证码登录)
            {
                userInfoEntity = await CheckSMSCode(model);
            }
            else
            {
                throw new ApiException("登录方式有误");
            }

            if (userInfoEntity.IsDisable)
            {
                throw new ApiException("该账户已禁用");
            }

            #region 验证账户类型


            //switch (model.UserIdentity)
            //{
            //    case 1:
            //        if ((userInfoEntity.IsAdmin == 1) || userInfoEntity.UserIdentity != UserIdentityEnum.牛人)
            //            throw new ApiException("登陆身份有误");
            //        break;

            //    case 2:
            //        if ((userInfoEntity.IsAdmin == 1) || userInfoEntity.UserIdentity != UserIdentityEnum.BOSS_HR)
            //            throw new ApiException("登陆身份有误");
            //        break;
            //    case 3:
            //        if (userInfoEntity.IsAdmin != 1)
            //            throw new ApiException("登陆身份有误");
            //        break;
            //    default:
            //        throw new ApiException("登陆身份有误");
            //}

            #endregion

            var loginResult = new LoginResultViewModel
            {
                UserId = userInfoEntity.ID,
                Token = TokenHelper.CreateJwtToken(userInfoEntity.ID.ToString(), userInfoEntity.IsAdmin),
                IsNeedPassword = !string.IsNullOrEmpty(userInfoEntity.Password),
                IsAdmin = userInfoEntity.IsAdmin,

            };
            return loginResult;
        }

        /// <summary>
        /// 第三方授权登陆
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public LoginResultViewModel OAuthLogin(OAuthLoginQueryModel model)
        {

            //if(model.UserIdentity)
            lock (model)
            {
                switch (model.OAuthType)
                {
                    case OAuthTypeEnum.WeChat:
                        return WeChatLogin(model);
                    default:
                        throw new ApiException("登陆类型有误");
                }
            }
        }

        private LoginResultViewModel WeChatLogin(OAuthLoginQueryModel model)
        {
            if (string.IsNullOrWhiteSpace(model.Code))
                throw new ApiException("code有误");

            //AccessTokenContainer.Register(WebConfig.WeCahtAppId, WebConfig.WeCahtAppSecert);
            //var AccessToken = OAuthApi.GetAccessTokenAsync(WebConfig.WeCahtAppId, WebConfig.WeCahtAppSecert, code).Result;
            var jsonResult = Senparc.Weixin.WxOpen.AdvancedAPIs.Sns.SnsApi.JsCode2Json(WebConfig.WeCahtAppId, WebConfig.WeCahtAppSecert, model.Code);
            if (jsonResult.errcode == ReturnCode.请求成功)
            {
                //lock (model)
                //{
                var userinfoList = _userInfoRepository.Query(u => u.WeChatOpenId == jsonResult.openid).Result.ToList();
                UserInfoEntity userinfo = null;
                if (userinfoList.Count > 0)
                {
                    userinfo = userinfoList[0];
                }
                if (userinfo == null)
                {  //创建用户 
                   //Senparc.Weixin.WxOpen.AdvancedAPIs.Sns.SnsApi.;
                    userinfo = CreateUser(new CreateUserModel
                    {
                        WeChatOpenId = jsonResult.openid,
                        WeChatUnionId = jsonResult.unionid,

                        UserInfo = model.UserInfo,
                    });
                }

                if (userinfo.IsDisable)
                {
                    throw new ApiException("该账户已禁用");
                }

                var unionId = "";
                var sessionBag = SessionContainer.UpdateSession(null, jsonResult.openid, jsonResult.session_key, unionId);

                //jsonResult.session_key; 保存session 到缓存
                CacheHelper.Set(jsonResult.openid, jsonResult.session_key);
                CacheHelper.Set($"sessionid_{jsonResult.session_key}", sessionBag.Key);

                return new LoginResultViewModel
                {
                    UserId = userinfo.ID,
                    Token = TokenHelper.CreateJwtToken(userinfo.ID.ToString(), userinfo.IsAdmin),

                    IsNeedPassword = !string.IsNullOrEmpty(userinfo.Password)
                };
                //}
            }
            else
            {
                throw new ApiException(jsonResult.errmsg);
            }
        }

        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> Register(RegisterQueryModel model)
        {
            var user = await _userInfoRepository.GetEntity(s => s.Phone == model.Phone);
            if (user != null)
            {
                throw new ApiException("手机号已经注册过了");
            }

            if (!await CheckPhoneCode(model.Phone, model.PhoneCode))//验证码验证
            {
                throw new ApiException("验证码错误");
            }

            if (model.ParentId != Guid.Empty)
            {
                //上级id
                var pruser = await _userInfoRepository.QueryById(model.ParentId);
                if (pruser != null)
                {
                    //邀请好友加积分
                    // await _creditService.AddCredit(CreditCategoryEnum.邀请好友, pruser.ID);
                }
            }


            if (user == null)
            {
                CreateUser(new CreateUserModel
                {
                    Phone = model.Phone,
                    ParentId = model.ParentId
                });
                return true;
            }

            throw new ApiException("注册失败");
        }

        /// <summary>
        /// 创建并注册用户信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private UserInfoEntity CreateUser(CreateUserModel model)
        {
            var username = "KeepAccounts" + DateTime.Now.GetHashCode();
            //头像保存路径

            var entity = new UserInfoEntity
            {
                CreateTime = DateTime.Now,
                HeaderImage = HttpHelper.DownloadHeader(model.UserInfo.avatarUrl),
                IsAdmin = 0,
                Phone = string.IsNullOrWhiteSpace(model.Phone) ? "" : model.Phone,
                LoginName = username,
                IsVip = false,
                IsDeleted = false,
                UserName = model.UserInfo.nickName,//用户名默认为空
                Password = "",
                Sex = (SexEnum)model.UserInfo.gender,
                PayPassword = "",
                ID = Guid.NewGuid(),
                UpdateTime = DateTime.Now,
                CreateUserID = Guid.Parse("00000000-0000-0000-0000-000000000000"),
                UpdateUserID = Guid.Parse("00000000-0000-0000-0000-000000000000"),
                WeChatOpenId = string.IsNullOrWhiteSpace(model.WeChatOpenId) ? "" : model.WeChatOpenId,
                WeChatUnionId = string.IsNullOrWhiteSpace(model.WeChatUnionId) ? "" : model.WeChatUnionId,
                ParentId = model.ParentId,
                BirthTime = DateTime.Now,

                Country = model.UserInfo.country,
                City = model.UserInfo.city,
                Province = model.UserInfo.province,
            };
            if (_userInfoRepository.Add(entity).Result > 0) return entity;
            throw new ApiException("注册失败");
        }
        /// <summary>
        /// 创建并注册用户信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private async Task<UserInfoEntity> CheckSMSCode(LoginQueryModel model)
        {
            if (!await CheckPhoneCode(model.Phone, model.PhoneCode))//验证码验证
            {
                throw new ApiException("验证码错误");
            }
            var user = (await _userInfoRepository.Query(t => !t.IsDeleted
        && t.Phone == model.Phone)).FirstOrDefault();
            if (user == null)
            {
                var username = "RHT" + DateTime.Now.GetHashCode();
                user = new UserInfoEntity
                {
                    CreateTime = DateTime.Now,
                    HeaderImage = "/Images/header.png",
                    IsAdmin = 0,
                    Phone = model.Phone,
                    LoginName = username,
                    IsVip = false,
                    IsDeleted = false,
                    UserName = username,
                    Password = "",
                    Sex = SexEnum.未知,
                    PayPassword = "",
                    ID = Guid.NewGuid(),
                    UpdateTime = DateTime.Now,
                    CreateUserID = Guid.Parse("00000000-0000-0000-0000-000000000000"),
                    UpdateUserID = Guid.Parse("00000000-0000-0000-0000-000000000000"),
                };
                await _userInfoRepository.Add(user);
                //注册+积分
                //  await _creditService.AddCredit(CreditCategoryEnum.注册, user.ID);
            }

            return user;
        }


        private void CheckLoginModel(LoginQueryModel model)
        {
            if (model.LoginType == LoginTypeEnum.密码登录 && string.IsNullOrWhiteSpace(model.Password))
            {
                throw new ApiException("请输入密码");
            }
            if (model.LoginType == LoginTypeEnum.验证码登录 && string.IsNullOrWhiteSpace(model.PhoneCode))
            {
                throw new ApiException("请输入验证码");
            }
            if (model.LoginType == LoginTypeEnum.验证码登录 && !ValidStringHelper.ValidPhoneNumber(model.Phone))
            {
                throw new ApiException("请输入正确的手机号");
            }

        }

        private async Task<UserInfoEntity> CheckPassword(LoginQueryModel model)
        {
            var password = MD5Helper.MD5Encrypt32(model.Password);
            var user = (await _userInfoRepository.Query(t => !t.IsDeleted
            && (t.Phone == model.Phone || t.LoginName == model.Phone)
            && t.Password == password)).FirstOrDefault();
            if (user == null)
            {
                throw new ApiException("用户名密码错误");
            }
            return user;
        }


        #region GetUserInfo
        /// <summary>
        /// 获得用户信息
        /// </summary>
        /// <returns></returns>
        public async Task<UserInfoResultViewModel> GetUserInfo()
        {
            var user = await _userInfoRepository.QueryById(_aspNetUser.UserId);
            if (user == null)
            {
                throw new ApiException("用户信息不存在");
            }
            user.HeaderImage = (!string.IsNullOrWhiteSpace(user.HeaderImage) && !user.HeaderImage.StartsWith("http")) ? WebConfig.WebSiteUrl + user.HeaderImage : user.HeaderImage;
            var model = user.MapTo<UserInfoResultViewModel>();
            model.ExpandedCount = await _userInfoRepository.QueryCount(t => t.ParentId == user.ID);
            // model.LearnedCount = await _coursePlayRepository.QueryCount(t => t.UserId == user.ID);

            return model;
        }
        #endregion

        /// <summary>
        /// 退出登陆 TODU
        /// </summary>
        /// <returns></returns>
        public async Task<bool> Logout()
        {
            return true;
        }

        #region 修改密码
        /// <summary>
        /// 修改密码
        /// </summary>
        /// <returns></returns>
        public async Task<bool> UpdatePassword(UpdatePasswordQueryModel model)
        {
            if (model.UpdatePasswordType == UpdatePasswordTypeEnum.修改密码 && string.IsNullOrWhiteSpace(model.OldPassword))
            {
                throw new ApiException("老密码不能为空");
            }

            if (string.IsNullOrWhiteSpace(model.NewPassword))
            {
                throw new ApiException("新密码不能为空");
            }

            var user = await _userInfoRepository.QueryById(_aspNetUser.UserId);
            if (user == null)
            {
                throw new ApiException("当前用户不存在");
            }
            if (model.UpdatePasswordType == UpdatePasswordTypeEnum.设置密码)
            {
                if (!string.IsNullOrWhiteSpace(user.Password))
                {
                    throw new ApiException("当前用户已设置过密码");
                }
                user.Password = MD5Helper.MD5Encrypt32(model.NewPassword);
            }
            else if (model.UpdatePasswordType == UpdatePasswordTypeEnum.修改密码)
            {
                if (user.Password != MD5Helper.MD5Encrypt32(model.OldPassword))
                {
                    throw new ApiException("旧密码错误");
                }
                user.Password = MD5Helper.MD5Encrypt32(model.NewPassword);
            }
            //else if (model.UpdatePasswordType == UpdatePasswordTypeEnum.找回密码)
            //{
            //    //TODO 找回密码用户不用登录 需要验证手机验证码
            //    user.Password = MD5Helper.MD5Encrypt32(model.NewPassword);
            //}
            else
            {
                throw new ApiException("设置密码类型错误");
            }
            return await _userInfoRepository.Update(user);
        }


        /// <summary>
        /// 找回密码
        /// </summary>
        /// <returns></returns>
        public async Task<bool> FindPassword(FindPasswordQueryModel model)
        {
            var user = await _userInfoRepository.GetEntity(u => !u.IsDeleted && u.Phone == model.Phone);
            if (user == null)
            {
                throw new ApiException("用户不存在");
            }

            if (string.IsNullOrWhiteSpace(model.NewPassword))
            {
                throw new ApiException("新密码不能为空");
            }
            if (!await this.CheckPhoneCode(model.Phone, model.Code))
            {
                throw new ApiException("验证码错误");
            }

            user.Password = MD5Helper.MD5Encrypt32(model.NewPassword);
            return await _userInfoRepository.Update(user);
        }


        /// <summary>
        /// 重置密码
        /// </summary>
        /// <returns></returns>
        public Task<bool> ResetPassword(ResetPasswordQueryModel model)
        {
            var user = _userInfoRepository.GetEntity(u => !u.IsDeleted && u.ID == model.Id).Result;
            if (user == null)
            {
                throw new ApiException("用户不存在");
            }

            if (string.IsNullOrWhiteSpace(model.NewPassword))
            {
                throw new ApiException("新密码不能为空");
            }

            if (model.NewPassword.Length < 6)
            {
                throw new ApiException("密码长度不能少于6位");
            }

            user.Password = MD5Helper.MD5Encrypt32(model.NewPassword);
            return _userInfoRepository.Update(user);
        }




        #endregion

        /// <summary>
        /// 修改个人信息
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public async Task<bool> UpdateUserInfo(UpdateUserInfoQueryModel query)
        {
            var user = await _userInfoRepository.QueryById(_aspNetUser.UserId);

            if (user == null) { throw new ApiException("个人信息有误"); }

            if (string.IsNullOrWhiteSpace(query.HeaderImage)) query.HeaderImage = user.HeaderImage;

            if (string.IsNullOrWhiteSpace(query.UserName)) query.UserName = user.UserName;


            query.HeaderImage = string.IsNullOrWhiteSpace(query.HeaderImage) ? user.HeaderImage : query.HeaderImage.Replace(WebConfig.WebSiteUrl, string.Empty);
            query.UserName = string.IsNullOrWhiteSpace(query.UserName) ? user.UserName : query.UserName;

            return await _userInfoRepository.Update(s => new UserInfoEntity { HeaderImage = query.HeaderImage, UserName = query.UserName, }, s => s.ID == _aspNetUser.UserId);
        }

        #region 验证码验证
        private async Task<bool> CheckPhoneCode(string phoneNumber, string code)
        {
            var smsEntity = await _smsRepository.GetPhoneCode(phoneNumber, SmsTypeEnum.验证码);
            if (smsEntity != null)
            {
                var model = JsonConvert.DeserializeObject<SmsPhoneCodeModel>(smsEntity.TemplateParameter);
                return code.Equals(model.code);
            }
            return false;
        }
        #endregion


        #region CURD
        public async Task<PageResultModel<UserInfoEntity>> FindList(UserInfoListQueryModel query)
        {
            query.WhereLambda = Expressionable.Create<UserInfoEntity>().
               //And(s => !s.IsDeleted).
               AndIF(!string.IsNullOrWhiteSpace(query.LoginName), s => s.LoginName.Contains(query.LoginName) || s.UserName.Contains(query.LoginName)).
               AndIF(query.IsAdmin, u => u.IsAdmin == 1).
               AndIF(!query.IsAdmin, u => u.IsAdmin != 1).

               ToExpression();

            return await _userInfoRepository.Pages<UserInfoEntity>(query);
        }

        /// <summary>
        /// 保存修改客户信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool Save(UserInfoEntity model)
        {
            CheckUser(model);

            lock (model)
            {
                if (_userInfoRepository.QueryCount(s => s.LoginName == model.LoginName && s.ID != model.ID).Result > 0)
                {
                    throw new ApiException("登录名不能重复");
                }

                if (_userInfoRepository.QueryCount(s => s.Phone == model.Phone && s.ID != model.ID).Result > 0)
                {
                    throw new ApiException("手机号不能重复");
                }

                model.HeaderImage = string.IsNullOrWhiteSpace(model.HeaderImage) ? "" : model.HeaderImage.Replace(WebConfig.WebSiteUrl, string.Empty);
                if (model.ID == Guid.Empty)
                { //保存
                    model.ID = Guid.NewGuid();
                    model.ParentId = Guid.Empty;
                    model.PayPassword = "";
                    model.Integral = 0;//

                    model.Password = MD5Helper.MD5Encrypt32(model.Password);
                    return _userInfoRepository.Add(model).Result > 0;
                }
                else
                { //修改 
                    return _userInfoRepository.Update(model).Result;
                }
            }
        }

        private void CheckUser(UserInfoEntity model)
        {
            if (model == null)
                throw new ApiException("保存信息有误");
            if (string.IsNullOrWhiteSpace(model.UserName))
                throw new ApiException("用户名不能为空");
            if (string.IsNullOrWhiteSpace(model.LoginName))
                throw new ApiException("登录名不能为空");
            if (string.IsNullOrWhiteSpace(model.Phone))
                throw new ApiException("手机号码不能为空");
            if (string.IsNullOrWhiteSpace(model.Password))
                throw new ApiException("密码不能为空");
            if (string.IsNullOrWhiteSpace(model.HeaderImage))
                throw new ApiException("头像不能为空");





        }

        /// <summary>
        /// 刷新token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task<LoginResultViewModel> RefreshToken(string token)
        {
            var userid = TokenHelper.DecryptToken(token);

            var userInfoEntity = await _userInfoRepository.QueryById(userid);

            var loginResult = new LoginResultViewModel
            {
                UserId = userInfoEntity.ID,
                Token = TokenHelper.CreateJwtToken(userInfoEntity.ID.ToString(), userInfoEntity.IsAdmin),
                IsNeedPassword = !string.IsNullOrEmpty(userInfoEntity.Password),
                IsAdmin = userInfoEntity.IsAdmin,

            };
            return loginResult;

        }
        #endregion



    }

}
